package cn.sykj.car.service.impl;

import cn.sykj.car.common.Const;
import cn.sykj.car.common.StatusCode;
import cn.sykj.car.entity.Operation;
import cn.sykj.car.entity.Roles;
import cn.sykj.car.entity.RolesPrivilege;
import cn.sykj.car.entity.UserRole;
import cn.sykj.car.exception.CommonException;
import cn.sykj.car.exception.ParameterInvalidException;
import cn.sykj.car.exception.RolesException;
import cn.sykj.car.mapper.RolesMapper;
import cn.sykj.car.service.IOperationService;
import cn.sykj.car.service.IRolesPrivilegeService;
import cn.sykj.car.service.IRolesService;
import cn.sykj.car.service.IUserRoleService;
import cn.sykj.car.utils.Utils;
import cn.sykj.car.vo.RolesVO;
import cn.sykj.car.vo.SysMenuVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author Yixu
 * @since 2018-11-29
 */
@Service
public class RolesServiceImpl extends ServiceImpl<RolesMapper, Roles> implements IRolesService {
    @Resource
    private IRolesPrivilegeService iRolesPrivilegeService;

    @Resource
    private IUserRoleService iUserRoleService;

    @Resource
    private IOperationService iOperationService;

    // 获取已添加的角色
    @Override
    public List<Roles> getRolesByUser(Integer userId) {
        return baseMapper.selectByUser(userId);
    }

    // 获取未添加的角色
    @Override
    public List<Roles> getWtjRolesByUser(Integer userId) {
        return baseMapper.selectWtjByUser(userId);
    }

    /**
     * 查询单条
     *
     * @param condition
     * @return
     * @author yuhao 2018-12-06 17:15
     */
    @Override
    public Roles selectOneRoles(Roles condition) {
        if (Utils.isEmpty(condition) || Utils.isEmpty(condition.getId())) {
            return null;
        }

        return this.getById(condition);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param condition
     * @return
     * @author yuhao 2018-12-06 17:15
     */
    @Override
    public Page<RolesVO> pageRoles(Page<RolesVO> page, RolesVO condition) {

        List<RolesVO> rolesList = baseMapper.findRoles(page, condition);
        for (RolesVO oneRole : rolesList) {
            // 查询该角色对应的操作权限
            oneRole.setOperationList(iOperationService.selectOperationsByRoleId(oneRole.getId()));
        }
        page.setRecords(rolesList);
        return page;
    }

    /**
     * 添加角色：同时添加菜单权限、相关用户、操作权限
     *
     * @param roles
     * @return
     * @throws Exception
     * @author yuhao 2018-12-07 11:45
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean insertRoles(RolesVO roles) throws Exception {
        if (Utils.isEmpty(roles)) {
            throw new ParameterInvalidException();
        }

        List<Roles> searchRoles;

        // 判断角色名称是否重复
        if (Utils.notEmpty(roles.getRoleName())) {
            QueryWrapper<Roles> condition = new QueryWrapper<>();
            condition.eq(Roles.ROLE_NAME, roles.getRoleName());
            searchRoles = this.list(condition);
            if (searchRoles.size() > 0) {
                throw new RolesException(StatusCode.ROLE_NAME_REPEAT.getCode(),
                        StatusCode.ROLE_NAME_REPEAT.getMsg());
            }
        }

        boolean ret = this.save(roles);
        if (ret) {

            // 添加菜单权限、相关用户
//            List<UserRole> userRoles = new ArrayList<>();

            // 菜单+权限
            if (Utils.notEmpty(roles.getMenuIdList())) {
                List<SysMenuVO> menuIds = roles.getMenuIdList();
                for (SysMenuVO menu : menuIds) {
                    RolesPrivilege nRolesPrivilege = new RolesPrivilege();
                    nRolesPrivilege.setPrivilegeType(Const.PRIVILEGE_TYPE_MENU);
                    nRolesPrivilege.setRolesId(roles.getId());
                    nRolesPrivilege.setRefId(menu.getId());
                    ret &= iRolesPrivilegeService.save(nRolesPrivilege);

                    // 拼凑权限
                    String codePre = "";
                    String codeSuf = "";
                    // 权限前缀String
                    if (Utils.notEmpty(menu.getControllerName())) {
                        codePre = menu.getControllerName();
                    }

                    // 权限后缀List<String>
                    if (Utils.notEmpty(menu.getOperationList())) {
                        List<String> suffixs = menu.getOperationList();
                        if(!suffixs.contains("*")&&!suffixs.contains("view")){
                            throw new CommonException(StatusCode.OPERATION_VALUE_MUST_CONTAIN_VIEW.getCode(),
                                    StatusCode.OPERATION_VALUE_MUST_CONTAIN_VIEW.getMsg());
                        }
                        if(suffixs.contains("*")){
                            codeSuf = "*,";
                        }else{
                            for (String suffixCode : suffixs) {
                                codeSuf += suffixCode + ",";
                            }
                        }
                    }

                    Operation operation = new Operation();
                    operation.setMenuId(nRolesPrivilege.getId());
                    if (Utils.notEmpty(codePre) && Utils.notEmpty(codeSuf)) {
                        codeSuf = codeSuf.substring(0, codeSuf.length() - 1);
                        operation.setPermissionCode(codePre + ":" + codeSuf);
                    }

                    ret &= iOperationService.save(operation);
                }
            }

            // 用户
//            if (Utils.notEmpty(roles.getUserIdList()) && roles.getUserIdList().size() > 0) {
//                List<Integer> userIds = roles.getUserIdList();
//                for (Integer id : userIds) {
//                    UserRole nUserRole = new UserRole();
//                    nUserRole.setUserId(id);
//                    nUserRole.setRoleId(roles.getId());
//                    userRoles.add(nUserRole);
//                }
//            }

        }
        return ret;
    }

    /**
     * 修改角色：同时修改菜单权限、相关用户、操作权限
     *
     * @param roles
     * @return
     * @throws Exception
     * @author yuhao 2018-12-07 11:46
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean updateRoles(RolesVO roles) throws Exception {

        if (Utils.isEmpty(roles) || Utils.isEmpty(roles.getId())) {
            throw new ParameterInvalidException();
        }
        Roles oRoles = this.getById(roles.getId());
        if (Utils.isEmpty(oRoles)) {
            throw new RolesException(StatusCode.ROLE_NOT_FOUND.getCode(),
                    StatusCode.ROLE_NOT_FOUND.getMsg());
        }

        List<Roles> searchRoles;

        // 判断除自己外角色名称是否重复
        if (Utils.notEmpty(roles.getRoleName())) {
            QueryWrapper<Roles> condition = new QueryWrapper<>();
            condition.eq(Roles.ROLE_NAME, roles.getRoleName()).ne("id", roles.getId());
            searchRoles = this.list(condition);
            if (searchRoles.size() > 0) {
                throw new RolesException(StatusCode.ROLE_NAME_REPEAT.getCode(),
                        StatusCode.ROLE_NAME_REPEAT.getMsg());
            }
        }

        boolean ret = this.saveOrUpdate(roles);
        if (ret) {

            // 按照roleId,批量删除roles_privilege  和 operation
            QueryWrapper<RolesPrivilege> rpCondition = new QueryWrapper<>();
            rpCondition.eq(RolesPrivilege.ROLES_ID,roles.getId());
            List<RolesPrivilege> rpList = iRolesPrivilegeService.list(rpCondition);
            if(rpList.size()>0){
                for(RolesPrivilege rp : rpList){
                    QueryWrapper<Operation> oCondition = new QueryWrapper<>();
                    oCondition.eq(Operation.MENU_ID,rp.getId());
                    ret &= iOperationService.remove(oCondition);
                    ret &= iRolesPrivilegeService.removeById(rp.getId());
                }
            }

            // 再批量添加菜单权限、操作权限
            if (Utils.notEmpty(roles.getMenuIdList())) {
                List<SysMenuVO> menuIds = roles.getMenuIdList();
                for (SysMenuVO menu : menuIds) {
                    RolesPrivilege nRolesPrivilege = new RolesPrivilege();
                    nRolesPrivilege.setPrivilegeType(Const.PRIVILEGE_TYPE_MENU);
                    nRolesPrivilege.setRolesId(roles.getId());
                    nRolesPrivilege.setRefId(menu.getId());
                    ret &= iRolesPrivilegeService.save(nRolesPrivilege);

                    // 拼凑权限
                    String codePre = "";
                    String codeSuf = "";
                    // 权限前缀String
                    if (Utils.notEmpty(menu.getControllerName())) {
                        codePre = menu.getControllerName();
                    }else{
                        continue;
                    }

                    // 权限后缀List<String>
                    if (Utils.notEmpty(menu.getOperationList())) {
                        List<String> suffixs = menu.getOperationList();
                        if(!suffixs.contains("*")&&!suffixs.contains("view")){
                            throw new CommonException(StatusCode.OPERATION_VALUE_MUST_CONTAIN_VIEW.getCode(),
                                    StatusCode.OPERATION_VALUE_MUST_CONTAIN_VIEW.getMsg());
                        }
                        if(suffixs.contains("*")){
                            codeSuf = "*,";
                        }else{
                            for (String suffixCode : suffixs) {
                                codeSuf += suffixCode + ",";
                            }
                        }
                    }

                    Operation operation = new Operation();
                    operation.setMenuId(nRolesPrivilege.getId());
                    if (Utils.notEmpty(codePre) && Utils.notEmpty(codeSuf)) {
                        codeSuf = codeSuf.substring(0, codeSuf.length() - 1);
                        operation.setPermissionCode(codePre + ":" + codeSuf);
                    }

                    ret &= iOperationService.save(operation);
                }
            }
        }
        return ret;
    }

    /**
     * 删除角色：如果有菜单权限、相关用户、操作权限，不能删，否则可删
     *
     * @param roles
     * @return
     * @throws Exception
     * @author yuhao 2018-12-07 11:47
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean deleteRoles(RolesVO roles) throws Exception {

        // 参数不存在
        if (Utils.isEmpty(roles) || Utils.isEmpty(roles.getId())) {
            throw new ParameterInvalidException();
        }

        // 判断当前角色是否存在
        Roles oRoles = this.getById(roles.getId());
        if(Utils.isEmpty(oRoles)){
            throw new RolesException(StatusCode.ROLE_NOT_FOUND.getCode(),
                    StatusCode.ROLE_NOT_FOUND.getMsg());
        }

        // 判断该角色是否有用户、是否有操作权限
        if(iRolesPrivilegeService.getByRoleId(roles.getId()).size()>0){
            throw new RolesException(StatusCode.ROLE_EXIST_MENU.getCode(),
                    StatusCode.ROLE_EXIST_MENU.getMsg());
        }
        if(iUserRoleService.getByRoleId(roles.getId()).size()>0){
            throw new RolesException(StatusCode.ROLE_EXIST_USER.getCode(),
                    StatusCode.ROLE_EXIST_USER.getMsg());
        }

        // 删除角色
        this.removeById(roles.getId());

        // 批量删除user_role  批量删除roles_privilege
        Map<String, Object> privilegeMap = new HashMap<>();
        privilegeMap.put(RolesPrivilege.ROLES_ID, roles.getId());
        iRolesPrivilegeService.removeByMap(privilegeMap);

        Map<String, Object> roleMap = new HashMap<>();
        roleMap.put(UserRole.ROLE_ID, roles.getId());
        boolean ret = iUserRoleService.removeByMap(roleMap);

        return ret;
    }

    /**
     * 查询角色/组织机构列表（不翻页）
     *
     * @param condition
     * @return
     */
    @Override
    public RolesVO selectAllRoles(RolesVO condition) throws Exception {

        // 先查全部角色
        List<Roles> allRoles = this.list();

        // key为pid,Map为pid对应的子集
        Map<Integer,Map<Integer,Roles>> rolesMap = new HashMap<Integer, Map<Integer,Roles>>();

        for (Roles sysRoles:allRoles){

            if(rolesMap.size()>0){
                if(Utils.isEmpty(rolesMap.get(sysRoles.getPid()))){
                    // 判断rolesMap的key不存在
                    Map<Integer,Roles> roleMap1 = new HashMap<>();
                    roleMap1.put(sysRoles.getId(),sysRoles);
                    rolesMap.put(sysRoles.getPid(),roleMap1);
                }else{
                    // 判断rolesMap的key存在
                    rolesMap.get(sysRoles.getPid()).put(sysRoles.getId(),sysRoles);
                }
            }else{
                Map<Integer,Roles> roleMap1 = new HashMap<>();
                roleMap1.put(sysRoles.getId(),sysRoles);
                rolesMap.put(sysRoles.getPid(),roleMap1);
            }

        }

        // 遍历rolesMap，将他封装成树形结构，利用递归
        RolesVO rolesVO = new RolesVO();
        rolesVO.setId(0);// 首层
        List<RolesVO> subRoles = getNode(0,rolesMap);
        rolesVO.setSubRolesList(subRoles);

        return rolesVO;
    }


    // 递归遍历角色
    public List<RolesVO> getNode(Integer pid,Map<Integer,Map<Integer,Roles>> allRolesMap) {
        List<RolesVO> retList = new ArrayList<>();
        if(allRolesMap.size()>0 && Utils.notEmpty(pid)){
            Map<Integer,Roles> sysRolesMap = allRolesMap.get(pid);
            if(Utils.notEmpty(sysRolesMap)){
                for(Map.Entry<Integer,Roles> entry : sysRolesMap.entrySet()){
                    Integer key = entry.getKey();
                    Roles sysRoles = entry.getValue();
                    RolesVO sysRolesVO = new RolesVO();
                    BeanUtils.copyProperties(sysRoles,sysRolesVO);
                    List<RolesVO> subRolesList = getNode(key,allRolesMap);
                    sysRolesVO.setSubRolesList(subRolesList);
                    retList.add(sysRolesVO);
                }
            }
        }
        return retList;
    }


}
